﻿using System;
using System.IO;
using System.Net.Sockets;

using Library.Util;
namespace Library.Network {
	public abstract class BaseMessage : IMessage {


		protected TcpClient Client;


		#region IMessage Members

		public abstract string GetMessageType();

		public void Send(TcpClient transferProtocol) {
			Client = transferProtocol;
			WriteAsciiString(GetMessageType());
			Send();
			Flush();
		}

		public void Receive(TcpClient transferProtocol) {
			Client = transferProtocol;
			Receive();
		}

		#endregion

		protected abstract void Send();

		protected abstract void Receive();


		protected void WriteBoolean(bool value) {
			Client.GetStream().Write(value);
		}

		protected void WriteInt16(Int16 value) {
			Client.GetStream().Write(value);
		}

		protected void WriteInt32(Int32 value) {
			Client.GetStream().Write(value);
		}

		protected void WriteInt64(Int64 value) {
			Client.GetStream().Write(value);
		}


		protected void WriteUInt16(UInt16 value) {
			Client.GetStream().Write(value);
		}

		protected void WriteUInt32(UInt32 value) {
			Client.GetStream().Write(value);
		}

		protected void WriteUInt64(UInt64 value) {
			Client.GetStream().Write(value);
		}


		protected void WriteDecimal(decimal value) {
			Client.GetStream().Write(value);
		}
		protected void WriteDouble(double value) {
			Client.GetStream().Write(value);
		}

		protected void WriteSingle(float value) {
			Client.GetStream().Write(value);
		}

		protected void WriteByte(byte value) {
			Client.GetStream().Write(value);
		}
		protected void WriteBytes(byte[] value) {
				Client.GetStream().Write(value);
		}

		protected void WriteAsciiString(string value) {
			Client.GetStream().WriteAnsi(value);
		}

		protected void WriteUnicodeString(string value) {
			Client.GetStream().WriteUnicode(value);
		}


		protected void Flush() {
			Client.GetStream().Flush();
		}



		//protected void WriteBytes(byte[] bytes, int offset, int count) {
		//  for (int i = offset; i < count; i++) {
		//    _sendBuffer.Add(bytes[i]);
		//    if (_sendBuffer.Count == DefaultBufferLeng) {
		//      Flush();
		//    }
		//  }
		//}

		protected void WriteFromStreamInput(Stream input) {
			int readed;
			do {
				var buffer = new byte[1024];
				readed = input.Read(buffer, 0, buffer.Length);
				Client.GetStream().Write(buffer, 0, readed);
				Flush();
			} while (readed > 0);
		}

		protected bool ReadBoolean() {
			bool value;
			Client.GetStream().Read(out value);
			return value;
		}

		protected Int16 ReadInt16() {
			Int16 value;
			Client.GetStream().Read(out value);
			return value;
		}




		protected Int32 ReadInt32() {
			Int32 value;
			Client.GetStream().Read(out value);
			return value;
		}

		protected Int64 ReadInt64() {
			Int64 value;
			Client.GetStream().Read(out value);
			return value;
		}


		protected UInt16 ReadUInt16() {
			UInt16 value;
			Client.GetStream().Read(out value);
			return value;
		}




		protected UInt32 ReadUInt32() {
			UInt32 value;
			Client.GetStream().Read(out value);
			return value;
		}

		protected UInt64 ReadUInt64() {
			UInt64 value;
			Client.GetStream().Read(out value);
			return value;
		}

		protected float ReadSingle() {
			float value;
			Client.GetStream().Read(out value);
			return value;
		}
		protected double ReadDouble() {
			double value;
			Client.GetStream().Read(out value);
			return value;
		}

		protected decimal ReadDecimal() {
			decimal value;
			Client.GetStream().Read(out value);
			return value;
		}


		/// <summary>
		/// read a unicode string in structure: LEN[4byte]DATA[LEN byte]
		/// </summary>
		/// <returns></returns>
		protected String ReadAsciiString() {
			string value;
			Client.GetStream().ReadAnsi(out value);
			return value;
		}


		/// <summary>
		/// read a unicode string in structure: LEN[4byte]DATA[LEN byte]
		/// </summary>
		/// <returns></returns>
		protected String ReadUnicodeString() {
			string value;
			Client.GetStream().ReadUnicode(out value);
			return value;
		}

		protected byte[] ReadSomeBytes(int numOfByte) {
			byte[] value;
			Client.GetStream().Read(numOfByte, out value);
			return value;
		}

		protected byte ReadByte() {
			byte value;
			Client.GetStream().Read(out value);
			return value;
		}




		public static string ReadAsciiString(Stream stream) {
			string value;
			stream.ReadAnsi(out value);
			return value;
		}
	}
}